package cn.com.libertymutual.core.exception;

import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;

import javax.mail.MessagingException;
import javax.xml.ws.soap.SOAPFaultException;

import org.springframework.ws.WebServiceException;
import org.springframework.ws.client.WebServiceTransportException;

import com.alibaba.fastjson.JSONException;
import com.google.common.base.Strings;


/**
 * 自定义异常,继承了根异常
 * @author 2016-05-18 10:10 zhaoyu
 *
 */

public class CustomLangException extends RuntimeException {


	

	/* @Override
    public Throwable fillInStackTrace() {
       return this;
    }*/
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -1242759822642447993L;
	//错误码
	private int errorCode = 9998;
	private String errorMessage = "未知错误!";
	
	//添加枚举类型的属性  author:tracy.liao date:2016-4-27
	private ExceptionEnums exceptionEnums;
	
	public CustomLangException() {
		super();
	}
	
	/**
	 * 异常构造器，在这个构造器中判断了异常的类型
	 * 
	 * @author zhaoyu 2016-05-18 10:14
	 * 
	 * @param e:异常的类型
	 * 
	 * */
	public CustomLangException( Throwable e ) {
		//如果是他自己
		if(e instanceof CustomLangException){
			this.errorCode = ((CustomLangException) e).getErrorCode();
			this.errorMessage = ((CustomLangException) e).getErrorMessage();
		//空指针异常
		}else if(e instanceof NullPointerException ){
			this.errorCode = LangExceptionEnums.NullPointerException_KEY.getCode();
			this.errorMessage = LangExceptionEnums.NullPointerException_KEY.getMessage();
		//方法参数错误	
		}else if(e instanceof IllegalArgumentException){
			this.errorCode = LangExceptionEnums.IllegalArgumentException_KEY.getCode();
			this.errorMessage =  LangExceptionEnums.IllegalArgumentException_KEY.getMessage();
		//数组负下标异常
		}else if(e instanceof NegativeArraySizeException){
			this.errorCode = LangExceptionEnums.NegativeArraySizeException_KEY.getCode();
			this.errorMessage = LangExceptionEnums.NegativeArraySizeException_KEY.getMessage();
		//算术条件异常。譬如：整数除零等
		}else if(e instanceof ArithmeticException){
			this.errorCode = LangExceptionEnums.ArithmeticException_KEY.getCode();
			this.errorMessage = LangExceptionEnums.ArithmeticException_KEY.getMessage();
		// 数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出
		}else if(e instanceof ArrayIndexOutOfBoundsException){
			this.errorCode = LangExceptionEnums.ArrayIndexOutOfBoundsException_KEY.getCode();
			this.errorMessage =  LangExceptionEnums.ArrayIndexOutOfBoundsException_KEY.getMessage();
		// 数组存储异常。当向数组中存放非数组声明类型对象时抛出
		}else if(e instanceof ArrayStoreException){
			this.errorCode = LangExceptionEnums.ArrayStoreException_KEY.getCode();
			this.errorMessage = LangExceptionEnums.ArrayStoreException_KEY.getMessage();
//		// 类造型异常。假设有类A和B（A不是B的父类或子类），O是A的实例，那么当强制将O构造为类B的实例时抛出该异常。该异常经常被称为强制类型转换异常：
//		}else if(e instanceof ClassCastException){
//			this.errorCode = LangExceptionEnums.ClassCastException_KEY.getCode();
//			StringBuilder errorMessageBuilder = new StringBuilder(LangExceptionEnums.ClassCastException_KEY.getMessage());
//			
//			this.errorMessage =  errorMessageBuilder.toString();
		// 找不到类异常。当应用试图根据字符串形式的类名构造类，而在遍历CLASSPAH之后找不到对应名称的class文件时，抛出该异常
		}else if(e instanceof ClassNotFoundException){
			this.errorCode = LangExceptionEnums.ClassNotFoundException_KEY.getCode();
			this.errorMessage = LangExceptionEnums.ClassNotFoundException_KEY.getMessage();
//			this.errorMessage =  errorMessageBuilder.toString();
		// 不支持克隆异常。当没有实现Cloneable接口或者不支持克隆方法时,调用其clone()方法则抛出
		}else if(e instanceof CloneNotSupportedException){
			this.errorCode = LangExceptionEnums.CloneNotSupportedException_KEY.getCode();			
			this.errorMessage =  LangExceptionEnums.CloneNotSupportedException_KEY.getMessage();
		// 枚举常量不存在异常。当应用试图通过名称和枚举类型访问一个枚举对象，但该枚举对象并不包含常量时，抛出该异常
		}else if(e instanceof EnumConstantNotPresentException){
			this.errorCode = LangExceptionEnums.EnumConstantNotPresentException_KEY.getCode();
			this.errorMessage =  LangExceptionEnums.EnumConstantNotPresentException_KEY.getMessage();
		// 违法的访问异常。当应用试图通过反射方式创建某个类的实例、访问该类属性、调用该类方法，而当时又无法访问类的、属性的、方法的或构造方法的定义时抛出该异常
		}else if(e instanceof IllegalAccessException){
			this.errorCode = LangExceptionEnums.IllegalAccessException_KEY.getCode();			
			this.errorMessage = LangExceptionEnums.IllegalAccessException_KEY.getMessage();
		// 违法的监控状态异常。当某个线程试图等待一个自己并不拥有的对象（O）的监控器或者通知其他线程等待该对象（O）的监控器时，抛出该异常
		}else if(e instanceof IllegalMonitorStateException){
			this.errorCode = LangExceptionEnums.IllegalMonitorStateException_KEY.getCode();
			this.errorMessage =  LangExceptionEnums.IllegalMonitorStateException_KEY.getMessage();
//		// 违法的状态异常。当在Java环境和应用尚未处于某个方法的合法调用状态，而调用了该方法时，抛出该异常 
//		}else if(e instanceof IllegalStateException){
//			this.errorCode = LangExceptionEnums.IllegalStateException_KEY.getCode();
//			StringBuilder errorMessageBuilder = new StringBuilder(LangExceptionEnums.IllegalStateException_KEY.getMessage());
//			
//			this.errorMessage =  errorMessageBuilder.toString();
		// 违法的线程状态异常。当县城尚未处于某个方法的合法调用状态，而调用了该方法时，抛出异常
		}else if(e instanceof IllegalThreadStateException){
			this.errorCode = LangExceptionEnums.IllegalThreadStateException_KEY.getCode();
			this.errorMessage =  LangExceptionEnums.IllegalThreadStateException_KEY.getMessage();
		// 索引越界异常。当访问某个序列的索引值小于0或大于等于序列大小时，抛出该异常： 
		}else if(e instanceof IndexOutOfBoundsException){
			this.errorCode = LangExceptionEnums.IndexOutOfBoundsException_KEY.getCode();
			this.errorMessage =  LangExceptionEnums.IndexOutOfBoundsException_KEY.getMessage();
		// 实例化异常。当试图通过newInstance()方法创建某个类的实例，而该类是一个抽象类或接口时，抛出该异常
		}else if(e instanceof InstantiationException){
			this.errorCode = LangExceptionEnums.InstantiationException_KEY.getCode();
			this.errorMessage =  LangExceptionEnums.InstantiationException_KEY.getMessage();
		// 被中止异常。当某个线程处于长时间的等待、休眠或其他暂停状态，而此时其他的线程通过Thread的interrupt方法终止该线程时抛出该异常
		}else if(e instanceof InterruptedException){
			this.errorCode = LangExceptionEnums.InterruptedException_KEY.getCode();			
			this.errorMessage =  LangExceptionEnums.InterruptedException_KEY.getMessage();
//		// 属性不存在异常。当访问某个类的不存在的属性时抛出该异常
//		}else if(e instanceof NoSuchFieldException){
//			this.errorCode = LangExceptionEnums.NoSuchFieldException_KEY.getCode();
//			StringBuilder errorMessageBuilder = new StringBuilder(LangExceptionEnums.NoSuchFieldException_KEY.getMessage());
//			
//			this.errorMessage =  errorMessageBuilder.toString();
//		// 方法不存在异常。当访问某个类的不存在的方法时抛出该异常
//		}else if(e instanceof NoSuchMethodException){
//			this.errorCode = LangExceptionEnums.NoSuchMethodException_KEY.getCode();
//			StringBuilder errorMessageBuilder = new StringBuilder(LangExceptionEnums.NoSuchMethodException_KEY.getMessage());
//			
//			this.errorMessage =  errorMessageBuilder.toString();
		// 数字格式异常。当试图将一个String转换为指定的数字类型，而该字符串确不满足数字类型要求的格式时，抛出该异常
		}else if(e instanceof NumberFormatException){
			this.errorCode = LangExceptionEnums.NumberFormatException_KEY.getCode();
			this.errorMessage =  LangExceptionEnums.NumberFormatException_KEY.getMessage();
		// 安全异常。由安全管理器抛出，用于指示违反安全情况的异常
		}else if(e instanceof SecurityException){
			this.errorCode = LangExceptionEnums.SecurityException_KEY.getCode();
			this.errorMessage =  LangExceptionEnums.SecurityException_KEY.getMessage();
		// 字符串索引越界异常。当使用索引值访问某个字符串中的字符，而该索引值小于0或大于等于序列大小时，抛出该异常：
		}else if(e instanceof StringIndexOutOfBoundsException){
			this.errorCode = LangExceptionEnums.StringIndexOutOfBoundsException_KEY.getCode();	
			this.errorMessage =  LangExceptionEnums.StringIndexOutOfBoundsException_KEY.getMessage();
//		// 类型不存在异常
//		}else if(e instanceof TypeNotPresentException){
//			this.errorCode = LangExceptionEnums.TypeNotPresentException_KEY.getCode();
//			StringBuilder errorMessageBuilder = new StringBuilder(LangExceptionEnums.TypeNotPresentException_KEY.getMessage());
		// 不支持的方法异常。指明请求的方法不被支持情况的异常： 
		}else if(e instanceof UnsupportedOperationException){
			this.errorCode = LangExceptionEnums.UnsupportedOperationException_KEY.getCode();
			this.errorMessage =  LangExceptionEnums.UnsupportedOperationException_KEY.getMessage();
		//json格式化错误
		}else if(e instanceof JSONException){
			this.errorCode = LangExceptionEnums.JSON_EXCEPTION.getCode();
			this.errorMessage = LangExceptionEnums.JSON_EXCEPTION.getMessage();
		//参数为空异常
		}else if(e instanceof ParameterNoTNullException){
			this.errorCode = ((ParameterNoTNullException) e).getErrorCode();
			this.errorMessage =  ((ParameterNoTNullException) e).getErrorMessage();
		//参数超范围异常
		}else if(e instanceof ParameterTooLongException){
			this.errorCode = ((ParameterTooLongException) e).getErrorCode();
			this.errorMessage =  ((ParameterTooLongException) e).getErrorMessage();
		//参数类型不正确异常
		}else if(e instanceof ParameterTypeErrorException){
			this.errorCode = ((ParameterTypeErrorException) e).getErrorCode();
			this.errorMessage =  ((ParameterTypeErrorException) e).getErrorMessage();
		//连接接口失败
		}else if(e instanceof MalformedURLException){
			this.errorCode = InterfaceExceptionEnums.CONNECTION_EXCEPTION.getCode();
			this.errorMessage = InterfaceExceptionEnums.CONNECTION_EXCEPTION.getMessage();
		//接口调用失败
		}else if(e instanceof WebServiceException){
			this.errorCode = InterfaceExceptionEnums.CALL_INTERFACE_EXCEPTION.getCode();
			this.errorMessage =  InterfaceExceptionEnums.CALL_INTERFACE_EXCEPTION.getMessage();
		//接口异常
		}else if(e instanceof WebServiceTransportException){
			this.errorCode = InterfaceExceptionEnums.WEBSERVICE_TRANSPORT_EXCEPTION.getCode();
			this.errorMessage = InterfaceExceptionEnums.WEBSERVICE_TRANSPORT_EXCEPTION.getMessage();
		//redis异常
		/*}else if(e instanceof JedisException){
			this.errorCode = LangExceptionEnums.REDIS_EXCEPTION_KEY.getCode();
			this.errorMessage = LangExceptionEnums.REDIS_EXCEPTION_KEY.getMessage();*/
		//邮件异常
		}else if(e instanceof MessagingException){
			this.errorCode = LangExceptionEnums.MESSAGING_EXCEPTION.getCode();
			this.errorMessage =  LangExceptionEnums.MESSAGING_EXCEPTION.getMessage();
		//不支持编码异常
		}else if(e instanceof UnsupportedEncodingException){
			this.errorCode = LangExceptionEnums.UNSUPPORTEDENCODINGEXCEPTION_KEY.getCode();
			this.errorMessage =  LangExceptionEnums.UNSUPPORTEDENCODINGEXCEPTION_KEY.getMessage();
		}
		else if( e instanceof SOAPFaultException ) {
			this.errorCode = LangExceptionEnums.WEBSERVICE_SOAP_IOEXCEPTION.getCode();
			this.errorMessage =  LangExceptionEnums.WEBSERVICE_SOAP_IOEXCEPTION.getMessage();
		}else if( e instanceof AppException ) {
				this.errorCode =  ((AppException) e).getErrorCode();
				this.errorMessage =  ((AppException) e).getErrorMessage();
		}else if( e instanceof ParameterNoTNullException ) {
			this.errorCode = ((ParameterNoTNullException) e).getErrorCode();
			this.errorMessage =  ((ParameterNoTNullException) e).getErrorMessage();
		}else if( e instanceof ParameterTooLongException ) {
			this.errorCode = ((ParameterTooLongException) e).getErrorCode();
			this.errorMessage =  ((ParameterTooLongException) e).getErrorMessage();
		}else if( e instanceof ParameterTypeErrorException ) {
			this.errorCode = ((ParameterTypeErrorException) e).getErrorCode();
			this.errorMessage =  ((ParameterTypeErrorException) e).getErrorMessage();
		}else if( e instanceof CustomFileException  ) {
			this.errorCode = ((CustomFileException) e).getErrorCode();
			this.errorMessage =  ((CustomFileException) e).getErrorMessage();
		}else if( e instanceof CustomJDBCException  ) {
			this.errorCode = ((CustomJDBCException) e).getErrorCode();
			this.errorMessage =  ((CustomJDBCException) e).getErrorMessage();
		//根异常。用以描述应用程序希望捕获的情况
		}else{
			this.errorCode = LangExceptionEnums.Exception_KEY.getCode();
			this.errorMessage =  e.getMessage();
		}
	}
	

	public CustomLangException( String message ) {
		super( message );
		errorMessage = message;
	}
	public CustomLangException( String message, Throwable e ) {
		super( message, e );
		errorMessage = message;
	}

	public CustomLangException( int errorCode, String message ) {
		super(message);
		this.errorCode = errorCode;
		this.errorMessage = message;
	}
	public CustomLangException( int errorCode, String message, Throwable e ) {
		super(message, e);
		this.errorCode = errorCode;
		this.errorMessage = message;
	}
	
	/**
	 * 添加枚举类型构造方法
	 * @author tracy.liao
	 * @date 2016-4-27
	 * @param exceptionEnums
	 * @param message
	 */
	public CustomLangException(ExceptionEnums exceptionEnums, String message){
		super(Strings.isNullOrEmpty(message) ? exceptionEnums.getMessage() :exceptionEnums.getMessage()+" "+ message );
		this.exceptionEnums=exceptionEnums;
		this.errorCode = exceptionEnums.getCode();
		this.errorMessage = Strings.isNullOrEmpty(message) ? exceptionEnums.getMessage() : exceptionEnums.getMessage()+" "+ message;
	}
	
	public CustomLangException(ExceptionEnums exceptionEnums){
		super(exceptionEnums.getMessage());
		this.exceptionEnums=exceptionEnums;
		this.errorCode = exceptionEnums.getCode();
		this.errorMessage = exceptionEnums.getMessage();
	}



	

	/**
	 * @return the exceptionEnums
	 */
	public ExceptionEnums getExceptionEnums() {
		return exceptionEnums;
	}

	/**
	 * @param exceptionEnums the exceptionEnums to set
	 */
	public void setExceptionEnums(ExceptionEnums exceptionEnums) {
		this.exceptionEnums = exceptionEnums;
	}

	public int getErrorCode() {
		return errorCode;
	}
	public String getErrorCodeStr() {
		return  String.valueOf(errorCode);
	}
	public String getErrorMessage() {
		return errorMessage;
	}
	
	/**获取错误码和错误信息*/
	public String getErrorCodeAndMessage(){
		
		return String.format("%d-%s", errorCode, Strings.isNullOrEmpty(errorMessage) ? "系统异常，如果多次出现，请联系管理员" : errorMessage );
	}
}
